/*
 * Licensed to the 南京汇海交通科技有限公司
 *
 * Copyright (c) 2025.
 * All rights reserved.
 *
 * 本软件属南京汇海交通科技有限公司所有，在未获得南京汇海交通科技有限公司正式授权情况下，任何企业和个人，不能获取、阅读、安装、传播本软件涉及的任何受知识产权保护的内容。
 */
package com.chframework.boot.web.servlets;

import com.chframework.boot.core.response.result.ApiResult;
import com.chframework.boot.core.response.status.ApiStatusEnum;
import com.chframework.common.exception.ApplicationException;
import com.chframework.common.thread.ForkJoinHelper;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import org.springframework.web.util.pattern.PathPattern;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.function.Function;
import java.util.stream.Collectors;

// 特别说明：
// - 添加`@Controller`注解是为了使切面能够拦截到`/path/list`的请求。
// - 为避免冲突，禁止MvcPathController再被`@ComponentScan`扫描到，它在SpringWebMvcAutoConfiguration中已经被显式声明为java bean。
@Controller
@RequestMapping("/project")
public class MvcPathController {

    private final RequestMappingHandlerMapping requestMappingHandlerMapping;

    public MvcPathController(RequestMappingHandlerMapping requestMappingHandlerMapping) {
        this.requestMappingHandlerMapping = requestMappingHandlerMapping;
    }

    /**
     * 获取 spring-webmvc工程中所有的Api-Path列表
     */
    @ResponseBody
    @RequestMapping("/path/list")
    public ApiResult<TreeMap<String, List<String>>> readApiList() throws ApplicationException {
        Function<Map.Entry<RequestMappingInfo, HandlerMethod>, List<String>> function =
                (entry) -> {
                    RequestMappingInfo requestMappingInfo = entry.getKey();

                    if (requestMappingInfo.getPatternsCondition() != null) {
                        return requestMappingInfo
                                .getPatternsCondition()
                                .getPatterns()
                                .parallelStream()
                                .collect(Collectors.toList());
                    } else if (requestMappingInfo.getPathPatternsCondition() != null) {
                        return requestMappingInfo
                                .getPathPatternsCondition()
                                .getPatterns()
                                .parallelStream()
                                .map(PathPattern::getPatternString)
                                .collect(Collectors.toList());
                    } else {
                        return Collections.emptyList();
                    }
                };

        try {
            return ApiResult.<TreeMap<String, List<String>>>build()
                    .setStatus(ApiStatusEnum.SUCCESS)
                    .setResult(ForkJoinHelper.execute(() -> requestMappingHandlerMapping.getHandlerMethods()
                            .entrySet()
                            .parallelStream()
                            .collect(Collectors.toMap(
                                            entry -> entry.getValue().getMethod().toGenericString(),
                                            function,
                                            (oldValue, newValue) -> newValue,
                                            TreeMap::new
                                    )
                            ))
                    );
        } catch (Exception e) {
            throw new ApplicationException(e);
        }
    }

}
